﻿using BCCommon;
using BCData.Common.Area;
using BCData.TMS.Agent.AgentAreaRecord;
using BCData.TMS.Agent.AgentRecord;
using BCDto.Sim.Admin.Admin;
using BCDto.TMS.Agent.AgentAreaRecord;
using BCEntity.Common.EntityNameConst;
using BCEntity.TMS.Agent.AgentAreaRecord;
using BCService.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BCService.TMS.Agent.AgentAreaRecord
{
    public class AgentAreaRecordService : IAgentAreaRecordService
    {
        private readonly IAgentAreaRecordData agentAreaRecordData;
        private readonly IAgentRecordData agentRecordData;
        private readonly IRedisService redisService;
        private readonly IProvinceData provinceData;
        private readonly ICityData cityData;
        private readonly ICountyData countyData;
        private readonly string key = string.Format("{0}", EntityNameConst.AgentAreaRecordEntity);
        public AgentAreaRecordService(IAgentAreaRecordData agentAreaRecordData,
            IAgentRecordData agentRecordData,
            IRedisService redisService,
            IProvinceData provinceData,
            ICityData cityData,
            ICountyData countyData)
        {
            this.agentAreaRecordData = agentAreaRecordData;
            this.agentRecordData = agentRecordData;
            this.redisService = redisService;
            this.provinceData = provinceData;
            this.cityData = cityData;
            this.countyData = countyData;
        }

        public AgentAreaRecordDto Add(AdminDto admin, long agentRecordId, AgentAreaRecordRequestDto requestDto)
        {
            var agentRecordEntity = this.agentRecordData.GetEntity(agentRecordId).Result;
            if (agentRecordEntity == null)
            {
                throw new ArgumentException("代理商信息不存在");
            }
            var resultList = this.agentAreaRecordData.GetByAgentRecordId(agentRecordId).Result;
            if (resultList.Any(p => p.ProvinceId == requestDto.ProvinceId && p.CityId == requestDto.CityId && p.CountyId == requestDto.CountyId))
            {
                throw new ArgumentException("该代理商已有此区域，不需重复添加");
            }
            var province = this.provinceData.GetProvince(requestDto.ProvinceId);
            if (province == null)
            {
                throw new ArgumentException("省份信息不存在");
            }
            var city = this.cityData.GetCity(requestDto.CityId);
            if (city == null)
            {
                throw new ArgumentException("市信息不存在");
            }
            var county = this.countyData.GetCounty(requestDto.CountyId);
            if (county == null)
            {
                throw new ArgumentException("区县信息不存在");
            }
            return this.agentAreaRecordData.Insert(new AgentAreaRecordEntity()
            {
                AgentRecordId = agentRecordId,
                ProvinceId = province.ProvinceId,
                ProvinceCode = province.ProvinceCode,
                CityId = city.CityId,
                CityCode = city.CityCode,
                CountyId = county.CountyId,
                CountyCode = county.CountyCode,
                CreateAdminId = admin.AdminId,
                CreateAdminName = admin.FullName,
                CreateTime = DateTime.Now,
                UpdateTime = DateTime.Now,
                EditAdminId = admin.AdminId,
                EditAdminName = admin.FullName
            }).GetAwaiter().GetResult().As<AgentAreaRecordDto>();
        }

        public IEnumerable<AgentAreaRecordDto> AgentAreaExistsList(AdminDto adminDto)
        {
            if (adminDto.AgentRecord != null)
            {
                var hasChildrenList = this.agentAreaRecordData.AgentAreaExistsList(adminDto.AgentRecord.AgentRecordId).GetAwaiter().GetResult();
                return hasChildrenList.As<IEnumerable<AgentAreaRecordDto>>();
            }
            else
            {
                var hasChildrenList = this.agentAreaRecordData.AgentAreaExistsList(null).GetAwaiter().GetResult();
                return hasChildrenList.As<IEnumerable<AgentAreaRecordDto>>();
            }
        }

        public bool CheckCountyAuthorize(string countyCode, long agentRecordId)
        {
            var list = this.agentAreaRecordData.GetByAgentRecordId(agentRecordId).Result;
            return list.Any(p => p.CountyCode == countyCode && !p.IsChildAgent);
        }
        #region 获取代理商区域省市区三级联动树形列表
        public List<AgentAreaTreeDto> GetAgentAreaTree(AdminDto adminDto)
        {
           
            if (adminDto.AgentRecord == null)
            {
                string cacheKey = this.redisService.GetKey(key, 0);
                var result = this.redisService.TryGet(cacheKey, () =>
                {
                    var existsList = this.AgentAreaExistsList(adminDto);
                    var list = this.countyData.GetCounties(null);
                    var provinceGroupList = list.GroupBy(p => p.ProvinceCode);
                    List<AgentAreaTreeDto> tree = new List<AgentAreaTreeDto>();
                    foreach (var item in provinceGroupList)
                    {
                        AgentAreaTreeDto province = new AgentAreaTreeDto();
                        province.ProvinceCode = item.Key;
                        province.ProvinceName = item.First().ProvinceName;
                        List<AgentCityTreeDto> cityList = new List<AgentCityTreeDto>();
                        var cityGroupList = item.GroupBy(p => p.CityCode);
                        foreach (var cityItem in cityGroupList)
                        {
                            AgentCityTreeDto city = new AgentCityTreeDto();
                            city.CityCode = cityItem.Key;
                            city.CityName = cityItem.First().CityName;
                            List<AgentCountyTreeDto> countyList = new List<AgentCountyTreeDto>();
                            var countyGroupList = cityItem.GroupBy(p => p.CountyCode);
                            foreach (var countyItem in countyGroupList)
                            {
                                AgentCountyTreeDto county = new AgentCountyTreeDto();
                                county.CountyCode = countyItem.Key;
                                county.CountyName = countyItem.First().CountyName;
                                county.Exists = existsList.Any(p => p.CountyCode == countyItem.Key);
                                countyList.Add(county);
                            }
                            city.Children = countyList;
                            cityList.Add(city);
                        }
                        province.Children = cityList;
                        tree.Add(province);

                    }
                    return tree;
                }, TimeSpan.FromDays(365));
                return result;
            }
            else
            {
                string cacheKey = this.redisService.GetKey(key, adminDto.AgentRecord.AgentRecordId);
                var result = this.redisService.TryGet(cacheKey, () =>
                {
                    var existsList = this.AgentAreaExistsList(adminDto);
                    var list = this.agentAreaRecordData.GetViewByAgentRecordId(adminDto.AgentRecord.AgentRecordId).Result;
                    var provinceGroupList = list.GroupBy(p => p.ProvinceCode);
                    List<AgentAreaTreeDto> tree = new List<AgentAreaTreeDto>();
                    foreach (var item in provinceGroupList)
                    {
                        AgentAreaTreeDto province = new AgentAreaTreeDto();
                        province.ProvinceCode = item.Key;
                        province.ProvinceName = item.First().ProvinceName;
                        List<AgentCityTreeDto> cityList = new List<AgentCityTreeDto>();
                        var cityGroupList = item.GroupBy(p => p.CityCode);
                        foreach (var cityItem in cityGroupList)
                        {
                            AgentCityTreeDto city = new AgentCityTreeDto();
                            city.CityCode = cityItem.Key;
                            city.CityName = cityItem.First().CityName;
                            List<AgentCountyTreeDto> countyList = new List<AgentCountyTreeDto>();
                            var countyGroupList = cityItem.GroupBy(p => p.CountyCode);
                            foreach (var countyItem in countyGroupList)
                            {
                                AgentCountyTreeDto county = new AgentCountyTreeDto();
                                county.CountyCode = countyItem.Key;
                                county.CountyName = countyItem.First().CountyName;
                                county.Exists = existsList.Any(p => p.CountyCode == countyItem.Key);
                                countyList.Add(county);
                            }
                            city.Children = countyList;
                            cityList.Add(city);
                        }
                        province.Children = cityList;
                        tree.Add(province);

                    }
                    return tree;
                }, TimeSpan.FromDays(365));
                return result;
            }
        }
        #endregion

        /// <summary>
        /// 根据区县编码获取底层代理商区域记录
        /// </summary>
        /// <param name="countyCode">区县编码</param>
        /// <returns></returns>
        public AgentAreaRecordDto GetLastLevelByCode(string countyCode)
        {
            string cacheKey = this.redisService.GetKey(key, countyCode);
            var result = redisService.TryGet(cacheKey, () =>
            {
                return agentAreaRecordData.GetLastLevelByCode(countyCode).GetAwaiter().GetResult().As<AgentAreaRecordDto>();
            },TimeSpan.FromDays(365));
            return result;
        }

        public void UpdateIsChildAgent(long agentAreaRecordId, string countyCode)
        {
            this.agentAreaRecordData.UpdateIsChildAgent(agentAreaRecordId, countyCode).GetAwaiter().GetResult();
            string cacheKey = this.redisService.GetKey(key, countyCode);
            this.redisService.DeleteAsync(cacheKey);
        }
    }
}
